#include <iostream>
#include <vector>
#include <limits>

using namespace std;

const int INF = numeric_limits<int>::max();

// 弗洛伊德算法计算多源最短路径
void floydWarshall(vector<vector<int>>& graph) {
    int n = graph.size();
    vector<vector<int>> dist = graph; // 复制图的邻接矩阵

    // 三重循环更新所有顶点对的最短路径
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (dist[i][k] != INF && dist[k][j] != INF && dist[i][j] > dist[i][k] + dist[k][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }

    // 打印最短路径结果
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (dist[i][j] == INF) {
                cout << "INF ";
            } else {
                cout << dist[i][j] << " ";
            }
        }
        cout << endl;
    }
}

int main() {
    // 定义图的顶点数和边
    int V = 4;
    vector<vector<int>> graph(V, vector<int>(V, INF));

    // 初始化图的邻接矩阵
    // 这里我们使用0表示两个顶点之间有直接的边，INF表示没有直接的边
    graph[0][1] = 2;
    graph[0][2] = 4;
    graph[1][2] = 1;
    graph[1][3] = 3;
    graph[2][3] = 1;

    // 对角线元素设置为0，因为每个顶点到自身的距离为0
    for (int i = 0; i < V; i++) {
        graph[i][i] = 0;
    }

    // 计算多源最短路径
    floydWarshall(graph);

    return 0;
}